package com.jtny.nytb.equipment.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jtny.component.dto.CurrentUserDTO;
import com.jtny.component.entity.LocalHolder;
import com.jtny.component.enums.GenericStatusEnum;
import com.jtny.component.exception.ServiceException;
import com.jtny.component.redis.core.RedisValueService;
import com.jtny.component.util.Assert;
import com.jtny.component.util.BeanUtils;
import com.jtny.component.util.CurrentUserUtils;

import com.jtny.nytb.config.datafactor.dto.*;
import com.jtny.nytb.config.datafactor.enums.DataParamSourceEnum;
import com.jtny.nytb.config.datafactor.service.DataParamEquipmentExtendService;
import com.jtny.nytb.equipment.dao.equipment.*;
import com.jtny.nytb.equipment.dao.dataparam.*;
import com.jtny.nytb.equipment.dao.model.ModelDAO;
import com.jtny.nytb.equipment.dao.rule.CodeRuleDictDAO;
import com.jtny.nytb.equipment.domain.equipment.EquipmentGatewayRelationDO;
import com.jtny.nytb.equipment.domain.equipment.EquipmentInfoDO;
import com.jtny.nytb.equipment.domain.dataparam.*;
import com.jtny.nytb.equipment.domain.rule.CodeRuleDictDO;
import com.jtny.nytb.equipment.dto.equipment.EquipmentModelPageQueryParamDTO;
import com.jtny.nytb.equipment.dto.dataparam.*;
import com.jtny.nytb.equipment.dto.device.DataParamCoreDTO;
import com.jtny.nytb.equipment.dto.device.EquipmentInfoDTO;
import com.jtny.nytb.equipment.dto.excel.ExcelEquipmentLabelDTO;
import com.jtny.nytb.equipment.enums.CodeRuleTypeEnum;
import com.jtny.nytb.equipment.errorcode.EquipmentModelErrorCodeEnum;
import com.jtny.nytb.equipment.pool.TenantDataCalThreadPool;
import com.jtny.nytb.property.CodeProperty;
import com.jtny.nytb.equipment.service.DataParamService;
import com.jtny.nytb.equipment.service.RedisService;
import com.jtny.nytb.equipment.utils.ThreadLocalUtils;
import com.jtny.nytb.equipment.vo.dataparam.ParamTempVO;
import com.jtny.nytb.equipment.vo.dataparam.*;
import com.jtny.nytb.equipment.vo.dataparam.LabelVO;
import lombok.AllArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 设备参量管理Biz
 *
 * @author 智慧能源中心 - 伍天宇
 * @package com.jtny.nytb.equipment.biz.impl
 * @fileName DataParamBizImpl.java
 * @createTime 2023年09月19日 16:43
 * @Copyright© 2023 jtny
 * 江投能源技术研究院 版权所有
 */
@Service
@AllArgsConstructor
public class DataParamServiceImpl implements DataParamService {
    private ModelDAO modelDAO;
    private DataParamTempDAO dataParamTempDAO;
    private AlarmTempDAO alarmTempDAO;
    private AlgorithmTempDAO algorithmTempDAO;
    private LabelTempDAO labelTempDAO;
    private ParamTempDAO paramTempDAO;
    private CodeRuleDictDAO codeRuleDictDAO;
    private EquipmentInfoDAO equipmentInfoDAO;
    private EquipmentParamDAO equipmentParamDAO;
    private EquipmentLabelDAO equipmentLabelDAO;
    private EquipmentSNDAO equipmentSNDAO;
    private EquipmentGatewayRelationDAO equipmentGatewayRelationDAO;





    private DataParamEquipmentExtendService dataParamEquipmentExtendService;
    private CodeProperty codeProperty;
    private RedisValueService redisValueService;
    private RedisService redis;


    public List<EquipmentInfoDTO> listByQueryParam(EquipmentModelPageQueryParamDTO equipmentModelPageQueryParamDTO) throws ServiceException {
        List<EquipmentInfoDO> equipmentInfoList = equipmentInfoDAO.selectList(buildWrapper(equipmentModelPageQueryParamDTO));
        return BeanUtils.copyToList(equipmentInfoList, EquipmentInfoDTO.class);
    }
    public List<Long> listEquipmentIdByQueryParam(EquipmentModelPageQueryParamDTO equipmentModelPageQueryParamDTO)
            throws ServiceException {
        List<EquipmentInfoDTO> equipmentInfoList = listByQueryParam(equipmentModelPageQueryParamDTO);
        if (CollUtil.isEmpty(equipmentInfoList)) {
            return CollUtil.newArrayList();
        }
        return equipmentInfoList.stream().map(EquipmentInfoDTO::getId).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<EquipmentInfoDO> buildWrapper(EquipmentModelPageQueryParamDTO equipmentModelPageQueryParamDTO) {
        LambdaQueryWrapper<EquipmentInfoDO> wrapper = Wrappers.<EquipmentInfoDO>lambdaQuery();
        Optional.ofNullable(equipmentModelPageQueryParamDTO.getStatus())
                .ifPresent(status -> wrapper.eq(EquipmentInfoDO::getStatus, status));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getId())
                .ifPresent(id -> wrapper.eq(EquipmentInfoDO::getId, id));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getModel())
                .ifPresent(model -> wrapper.eq(EquipmentInfoDO::getModel, model));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getType())
                .ifPresent(type -> wrapper.eq(EquipmentInfoDO::getType, type));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getBrand())
                .ifPresent(brand -> wrapper.eq(EquipmentInfoDO::getBrand, brand));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getCode())
                .ifPresent(code -> wrapper.eq(EquipmentInfoDO::getCode, code));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getName())
                .ifPresent(name -> wrapper.like(EquipmentInfoDO::getName, name));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getAreaId())
                .ifPresent(areaId -> wrapper.eq(EquipmentInfoDO::getAreaId, areaId));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getAreaIdList())
                .ifPresent(areaIdList -> wrapper.in(EquipmentInfoDO::getAreaId, areaIdList));

        Optional.ofNullable(equipmentModelPageQueryParamDTO.getDockIdentifier())
                .ifPresent(dockIdentifier -> wrapper.eq(EquipmentInfoDO::getDockIdentifier, dockIdentifier));
        if (CollectionUtil.isNotEmpty(equipmentModelPageQueryParamDTO.getEquipmentIdList())) {
            wrapper.in(EquipmentInfoDO::getId, equipmentModelPageQueryParamDTO.getEquipmentIdList());
        }
        return wrapper;
    }



    /**
     * 保存 设备参量
     *
     * @param dataParamTempVO {@link //DataParamTempVO} 参量
     * @return {@link Boolean}
     */
    @Override
    public Boolean save(DataParamInfoVO dataParamTempVO) {
        DataParam4EquipmentDTO dataParamEquipment = toBuildDataParamEquipment(dataParamTempVO);
        return dataParamEquipmentExtendService.saveDataParamEquipmentExtendBatch(CollUtil.newArrayList(dataParamEquipment));
    }

    /**
     * 更新 设备参量
     *
     * @param dataParamTempVO {@link DataParamInfoVO} 参量
     * @return {@link Boolean}
     */
    @Override
    public Boolean update(DataParamInfoVO dataParamTempVO) {
        DataParam4EquipmentDTO dataParamEquipment = toBuildDataParamEquipment(dataParamTempVO);
        dataParamEquipment.getDataParam4EquipmentExtend().setDataParamId(dataParamTempVO.getId());
        return dataParamEquipmentExtendService.updateDataParamEquipmentExtendBatch(CollUtil.newArrayList(dataParamEquipment));
    }


    /**
     * 根据id查询 设备参量
     *
     * @param id 设备参量id
     * @return {@link //DataParamTempVO}
     */
    @Override
    public DataParamInfoVO getById(Long id) {
        DataParam4EquipmentDTO dataParam4Equipment = dataParamEquipmentExtendService.getDataParam4EquipmentByDataParamId(id);
        ConfigDataParamManagementDTO configDataParamManagementDTO = dataParam4Equipment.getConfigDataParamManagement();
        DataParamInfoVO result = new DataParamInfoVO(configDataParamManagementDTO);

        Integer source = result.getSource();
        if (DataParamSourceEnum.SYSTEM_CALCULATE.getCode().equals(source)) {
            AlgorithmVO algorithm = new AlgorithmVO(configDataParamManagementDTO.getConfigAlgorithDTO());
            if (CollUtil.isEmpty(configDataParamManagementDTO.getConfigParamDTOList())) {
                algorithm.setConfigParamList(new ArrayList<>());
            } else {
                algorithm.setConfigParamList(configDataParamManagementDTO.getConfigParamDTOList()
                        .stream().map(ParamTempVO::new).collect(Collectors.toList()));
            }
            result.setAlgorithm(algorithm);

            FrequencyVO frequency = new FrequencyVO();
            frequency.setFrequency(configDataParamManagementDTO.getFrequency());
            frequency.setFrequencyUnit(configDataParamManagementDTO.getFrequencyUnit());
            result.setFrequency(frequency);
        } else if (DataParamSourceEnum.SYSTEM_AUTO_COLLECT.getCode().equals(source)) {
            FrequencyVO frequency = new FrequencyVO();
            frequency.setFrequency(configDataParamManagementDTO.getFrequency());
            frequency.setFrequencyUnit(configDataParamManagementDTO.getFrequencyUnit());
            result.setFrequency(frequency);
        }
        // 数据转换
        if (CollUtil.isNotEmpty(configDataParamManagementDTO.getConfigAlarmDTOList())) {
            result.setAlarmList(configDataParamManagementDTO.getConfigAlarmDTOList()
                    .stream().map(AlarmVO::new).collect(Collectors.toList()));
        }


        DataParam4EquipmentExtendDTO extend = dataParam4Equipment.getDataParam4EquipmentExtend();
        result.setEquipmentId(extend.getEquipmentId());
        result.setEquipmentCode(extend.getEquipmentCode());
        result.setEquipmentName(extend.getEquipmentName());
        result.setReportIdentifier(extend.getReportIdentifier());
        result.setPowerCheckDisplay(extend.getPowerCheckDisplay());
        return result;
    }



    /**
     * 按规则字典 ID 移动数据参量
     *
     * @param equipmentId   设备 ID
     * @param equipmentCode 设备 code
     */
    @Override
    public void backDataParam(Long equipmentId, String equipmentCode) {
        EquipmentModelPageQueryParamDTO equipmentModelPageQueryParamDTO = new EquipmentModelPageQueryParamDTO();
        equipmentModelPageQueryParamDTO.setId(equipmentId);
        // 删除参量
        dataParamEquipmentExtendService.deleteByDataParamEquipmentIds(CollUtil.newArrayList(equipmentId));
    }

    /**
     * 按规则字典 ID 移动数据参量 （常规添加/修改设备）
     *
     * @param ruleDictIds   规则字典 ID
     * @param equipmentId   设备 ID
     * @param equipmentCode 设备 code
     * @param labelList     标签列表
     * @return {@link List<Long>}
     */
    @Override
    public void moveDataParamByRuleDictIds(CodeRuleTypeEnum typeEnum,
                                           List<String> ruleDictIds,
                                           Long equipmentId,
                                           String equipmentCode,
                                           String equipmentName,
                                           List<LabelVO> labelList) {
        Assert.notNull(ruleDictIds, "规则字典 ID 不能为空");
        // 过滤掉随机数和顺序数
        List<Long> ruleDictIdList = ruleDictIds.stream()
                .filter(dict -> !(dict.startsWith("#") || dict.startsWith("%")))
                .map(Long::parseLong).collect(Collectors.toList());
        // 所有规则字典
        List<CodeRuleDictDO> codeRuleDictList = codeRuleDictDAO
                .selectList(Wrappers.<CodeRuleDictDO>lambdaQuery()
                        .in(CodeRuleDictDO::getId, ruleDictIdList));
        // 所有规则字典的规则id
        List<Long> ruleIdList = codeRuleDictList.stream()
                .map(CodeRuleDictDO::getRuleId)
                .distinct()
                .collect(Collectors.toList());
        // 所有数据
        List<DataParamTempDTO> dataParamTempList= CollUtil.newArrayList();
        if (CollUtil.isEmpty(ruleIdList)) {
            dataParamTempList = CollUtil.newArrayList();
        }
        else {
            List<DataParamTempDO> dataParamTempDOS = dataParamTempDAO.selectList(Wrappers.<DataParamTempDO>lambdaQuery()
                    .eq(DataParamTempDO::getRelationType, 1)
                    .in(DataParamTempDO::getRelationId, ruleIdList));

            dataParamTempList = dataParamTempDOS.stream()
                    .map(this::buildDataParamTempDTO)
                    .collect(Collectors.toList());
        }

        if (CollUtil.isNotEmpty(dataParamTempList)) {
            List<DataParam4EquipmentDTO> toSaveList = transformDataParamTemp4EquipmentList(dataParamTempList, equipmentId, equipmentCode, equipmentName, labelList);
            dataParamEquipmentExtendService.saveDataParamEquipmentExtendBatch(toSaveList);
        }
    }
    private DataParamTempDTO buildDataParamTempDTO(DataParamTempDO paramTempDO) {
        DataParamTempDTO dataParamTempDTO = BeanUtils.copyToObject(paramTempDO, DataParamTempDTO.class);
        Long id = paramTempDO.getId();
        Integer source = paramTempDO.getSource();
        // 设置算法及参数
        if (source != null && source == 2) {
            TempAlgorithmRelationDO algorithmRelation = algorithmTempDAO
                    .selectOne(new LambdaQueryWrapper<TempAlgorithmRelationDO>()
                            .eq(TempAlgorithmRelationDO::getDataParamId, id)
                            .last("limit 1"));
            AlgorithmTempDTO algorithmTemp = BeanUtils.copyToObject(algorithmRelation, AlgorithmTempDTO.class);
            // 设置参数
            if (algorithmTemp != null) {
                List<TempParamRelationDO> tempParamRelationList = paramTempDAO.selectList(new LambdaQueryWrapper<TempParamRelationDO>()
                        .eq(TempParamRelationDO::getDataParamId, id));
                List<ParamTempDTO> paramTempList = BeanUtils.copyToList(tempParamRelationList, ParamTempDTO.class);
                algorithmTemp.setParamTempList(paramTempList);
            }
            dataParamTempDTO.setAlgorithm(algorithmTemp);
        }
        // 设置报警
        List<AlarmTempDO> alarmTempList = alarmTempDAO.selectList(new LambdaQueryWrapper<AlarmTempDO>()
                .eq(AlarmTempDO::getDataParamId, id));
        dataParamTempDTO.setAlarmList(BeanUtils.copyToList(alarmTempList, AlarmTempDTO.class));
        // 设置标签
        List<LabelTempDO> labelTempList = labelTempDAO.selectList(new LambdaQueryWrapper<LabelTempDO>()
                .eq(LabelTempDO::getDataParamId, id));
        dataParamTempDTO.setLabelList(BeanUtils.copyToList(labelTempList, LabelTempDTO.class));
        return dataParamTempDTO;
    }

    /**
     * 按设备模型 ID 移动数据参量 （规则添加/修改设备）
     *
     * @param modelId       规则字典 ID
     * @param equipmentId   设备 ID
     * @param equipmentCode 设备 code
     * @return {@link List<Long>}
     */
    @Override
    public void moveDataParamByModelId(CodeRuleTypeEnum typeEnum,
                                       Long modelId,
                                       Long equipmentId,
                                       String equipmentCode,
                                       String equipmentName,
                                       List<LabelVO> labelList) {
        Assert.notNull(modelId, "规则字典 ID 不能为空");
        List<DataParamTempDO> dataParamTempDOS = dataParamTempDAO.selectList(Wrappers.<DataParamTempDO>lambdaQuery()
                .eq(DataParamTempDO::getRelationType, 2)
                .eq(DataParamTempDO::getRelationId, modelId));
        List<DataParamTempDTO> dataParamTempList = dataParamTempDOS.stream()
                .map(this::buildDataParamTempDTO)
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(dataParamTempList)) {
            List<DataParam4EquipmentDTO> toUpdateList = transformDataParamTemp4EquipmentList(dataParamTempList, equipmentId, equipmentCode, equipmentName, labelList);
            dataParamEquipmentExtendService.saveDataParamEquipmentExtendBatch(toUpdateList);
        }
    }

    /**
     * 复制设备 移动数据参量 （规则添加/修改设备）
     *
     * @param copyId        被复制的设备 ID
     * @param copyCode      被复制的设备 code
     * @param equipmentId   设备 ID
     * @param equipmentCode 设备 code
     * @return {@link List<Long>}
     */
    @Override
    public void copyDataParam(Long copyId,
                              String copyCode,
                              Long equipmentId,
                              String equipmentCode,
                              String equipmentName,
                              List<LabelVO> labelList) {
        // 获取到参量
        List<DataParam4EquipmentDTO> dataParam4EquipmentList = dataParamEquipmentExtendService.listDataParamByEquipmentId(copyId);
        transformDataParam4EquipmentList(dataParam4EquipmentList, equipmentId, equipmentCode, equipmentName);
        dataParamEquipmentExtendService.saveDataParamEquipmentExtendBatch(dataParam4EquipmentList);
    }

    /**
     * 转换数据参数4 设备清单
     *
     * @param oldList       数据参数4 设备清单
     * @param equipmentId   设备 ID
     * @param equipmentCode 设备代码
     * @return {@link List}<{@link DataParam4EquipmentDTO}>
     */
    private List<DataParam4EquipmentDTO> transformDataParamTemp4EquipmentList(List<DataParamTempDTO> oldList,
                                                                              Long equipmentId,
                                                                              String equipmentCode,
                                                                              String equipmentName,
                                                                              List<LabelVO> labelList) {
        List<DataParam4EquipmentDTO> result = new ArrayList<>();
        oldList.forEach(item -> {
            DataParam4EquipmentDTO dto = new DataParam4EquipmentDTO();
            // 清除ID和code 设置名字
            ConfigDataParamManagementDTO configDataParamManagementDTO =
                    toConfigDataParamManagementDTO(item, equipmentName, equipmentId, labelList);
            configDataParamManagementDTO.setStatus(GenericStatusEnum.DISABLE.getValue());
            dto.setConfigDataParamManagement(configDataParamManagementDTO);
            DataParam4EquipmentExtendDTO extend = new DataParam4EquipmentExtendDTO();
            extend.setEquipmentId(equipmentId);
            extend.setEquipmentCode(equipmentCode);
            extend.setEquipmentName(equipmentName);
            extend.setIsFromRule(item.getIsCopyFromRule());
            extend.setPowerCheckDisplay(item.getPowerCheckDisplay());
            extend.setReportIdentifier(item.getReportIdentifier());
            dto.setDataParam4EquipmentExtend(extend);
            result.add(dto);
        });
        return result;
    }

    /**
     * 转换数据参数4 设备清单
     *
     * @param oldList       数据参数4 设备清单
     * @param equipmentId   设备 ID
     * @param equipmentCode 设备代码
     * @return {@link List}<{@link DataParam4EquipmentDTO}>
     */
    private void transformDataParam4EquipmentList(List<DataParam4EquipmentDTO> oldList,
                                                  Long equipmentId,
                                                  String equipmentCode,
                                                  String equipmentName) {
        oldList.forEach(item -> {
            ConfigDataParamManagementDTO configDataParamManagement = item.getConfigDataParamManagement();
            // 清除ID和code 设置名字
            configDataParamManagement.setCode(null);
            configDataParamManagement.setId(null);
            configDataParamManagement.setName(equipmentName + StrUtil.DASHED + configDataParamManagement.getUnifiedIdentifierName());
            configDataParamManagement.setStatus(GenericStatusEnum.DISABLE.getValue());
            DataParam4EquipmentExtendDTO extend = item.getDataParam4EquipmentExtend();
            extend.setId(null);
            extend.setEquipmentId(equipmentId);
            extend.setEquipmentCode(equipmentCode);
            extend.setEquipmentName(equipmentName);
            extend.setDataParamId(null);
            extend.setDataParamCode(null);
        });
    }

    private TenantDataCalThreadPool tenantDataCalThreadPool;

    /**
     * 导入数据参数
     *
     * @param dataParamTempList 数据参数临时列表
     */
    @Override
    @Async
    public void importDataParam(String tenantId, List<DataParam4EquipmentDTO> dataParamTempList) {
//        List<List<DataParam4EquipmentDTO>> split = CollUtil.split(dataParamTempList, 100);

        List<CompletableFuture> completableFutures = new ArrayList<>();
//        split.forEach(list ->
        completableFutures.add(CompletableFuture.runAsync(() -> {
            try {
                ThreadLocalUtils.setTenantCode(tenantId);
                dataParamEquipmentExtendService.saveDataParamEquipmentExtendBatch(dataParamTempList);
            } finally {
                ThreadLocalUtils.localTenantCode.remove();
            }
        }, tenantDataCalThreadPool));
//        );
        CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[completableFutures.size()])).join();
    }

    /**
     * 导入数据参数（模型）
     *
     * @param currentUser
     * @param mapEquipmentName
     * @param equipmentNameModelNameMap
     */
    @Override
    @Async
    public void importDataParamModel(CurrentUserDTO currentUser,
                                     Map<String, EquipmentInfoDTO> mapEquipmentName,
                                     Map<String, String> equipmentNameModelNameMap) {
        ThreadLocalUtils.setCurrentUser(currentUser);
        List<String> modelNameList = equipmentNameModelNameMap.values().stream().distinct().collect(Collectors.toList());
        Map<String, List<DataParam4EquipmentDTO>> mapModelNameDataParam = mapDataParamTempByModelName(modelNameList);
        Map<String, DataParam4EquipmentExtendDTO> mapEquipmentExtend = mapDataParamEquipmentExtendByEquipmentName(mapEquipmentName);
        Map<String, List<ConfigLabelDTO>> mapEquipmentNameLabel = mapLabelByEquipmentName(equipmentNameModelNameMap.keySet());
        List<CompletableFuture> completableFutures = new ArrayList<>();
        completableFutures.add(CompletableFuture.runAsync(() -> {
            try {
                ThreadLocalUtils.setTenantCode(currentUser.getTenantId());
                EquipmentModelDataParamDTO toSave = new EquipmentModelDataParamDTO(equipmentNameModelNameMap,
                        mapModelNameDataParam,
                        mapEquipmentExtend,
                        mapEquipmentNameLabel);
                dataParamEquipmentExtendService.importDataParamEquipmentExtend(toSave);
            } finally {
                ThreadLocalUtils.localTenantCode.remove();
            }
        }, tenantDataCalThreadPool));
        CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[completableFutures.size()])).join();
    }


    private Map<String, List<ConfigLabelDTO>> mapLabelByEquipmentName(Set<String> equipmentName) {
        Map<String, List<ConfigLabelDTO>> result = new HashMap<>();
        equipmentName.forEach(item -> {
            List<ExcelEquipmentLabelDTO> tempList = redis.getRedisKey4LabelList(item);
            if (CollUtil.isNotEmpty(tempList)) {
                result.put(item, BeanUtils.copyToList(tempList, ConfigLabelDTO.class));
            }
        });
        return result;
    }

    private Map<String, DataParam4EquipmentExtendDTO> mapDataParamEquipmentExtendByEquipmentName(Map<String, EquipmentInfoDTO> mapEquipmentName) {
        Map<String, DataParam4EquipmentExtendDTO> result = new HashMap<>();
        mapEquipmentName.forEach((key, value) -> {
            DataParam4EquipmentExtendDTO extend = new DataParam4EquipmentExtendDTO();
            extend.setEquipmentId(value.getId());
            extend.setEquipmentCode(value.getCode());
            extend.setEquipmentName(value.getName());
            result.put(key, extend);
        });
        return result;
    }

    private Map<String, List<DataParam4EquipmentDTO>> mapDataParamTempByModelName(List<String> modelNameList) {
        Map<String, List<DataParam4EquipmentDTO>> result = new HashMap<>();
        Map<String, List<DataParamTempDTO>> tempMap = redis.mapDataParamTempByModelNameList(modelNameList);
        tempMap.forEach((key, value) -> {
            List<DataParam4EquipmentDTO> tempList = new ArrayList<>();
            value.forEach(item -> {
                DataParamTempVO tempVO = new DataParamTempVO(item);
                ConfigDataParamManagementDTO configDataParamManagementImport = toConfigDataParamManagementImport(tempVO);
                DataParam4EquipmentExtendDTO extend = new DataParam4EquipmentExtendDTO();
                extend.setIsFromRule(Boolean.FALSE);
                extend.setPowerCheckDisplay(item.getPowerCheckDisplay());
                extend.setReportIdentifier(item.getReportIdentifier());
                DataParam4EquipmentDTO dto = new DataParam4EquipmentDTO();
                dto.setConfigDataParamManagement(configDataParamManagementImport);
                dto.setDataParam4EquipmentExtend(extend);
                tempList.add(dto);
            });
            result.put(key, tempList);
        });
        return result;
    }

    @Override
    public List<DataParam4EquipmentDTO> toDataParam4EquipmentList(List<DataParamTempVO> dataParamTempList) {
        List<DataParam4EquipmentDTO> result = new ArrayList<>();
        dataParamTempList.forEach(item -> {
            DataParam4EquipmentDTO dto = new DataParam4EquipmentDTO();
            ConfigDataParamManagementDTO configDataParamManagement = toConfigDataParamManagementImport(item);
            dto.setConfigDataParamManagement(configDataParamManagement);
            DataParam4EquipmentExtendDTO extend = new DataParam4EquipmentExtendDTO();
            extend.setEquipmentId(item.getEquipmentId());
            extend.setEquipmentCode(item.getEquipmentCode());
            extend.setEquipmentName(item.getEquipmentName());
            extend.setIsFromRule(Boolean.FALSE);
            extend.setPowerCheckDisplay(item.getPowerCheckDisplay());
            extend.setReportIdentifier(item.getReportIdentifier());
            dto.setDataParam4EquipmentExtend(extend);
            result.add(dto);
        });
        return result;
    }

    private ConfigDataParamManagementDTO toConfigDataParamManagementImport(DataParamTempVO tempVO) {
        ConfigDataParamManagementDTO result = tempVO.buildConfigDataParamManagementDTO();
        // 设置用户信息
        CurrentUserDTO currentUser = LocalHolder.getCurrentUser();
        if (ObjectUtil.isNull(currentUser)) {
            currentUser = ThreadLocalUtils.getCurrentUser();
        }
        CurrentUserUtils.setCreateDefaultField(result, currentUser);
        String equipmentName = tempVO.getEquipmentName();
        if (StrUtil.isNotBlank(equipmentName)) {
            // 设置参量名称
            result.setName(equipmentName + result.getUnifiedIdentifierName());
            // 补充参量标签
            /*List<ExcelEquipmentLabelDTO> redisKey4LabelList = redis.getRedisKey4LabelList(equipmentName);
            if (CollUtil.isNotEmpty(redisKey4LabelList)) {
                List<ConfigLabelDTO> configLabelDTOList = result.getConfigLabelDTOList();
                if (CollUtil.isNotEmpty(configLabelDTOList)) {
                    configLabelDTOList.addAll(BeanUtils.copyToList(redisKey4LabelList, ConfigLabelDTO.class));
                    result.setConfigLabelDTOList(configLabelDTOList);
                } else {
                    result.setConfigLabelDTOList(BeanUtils.copyToList(redisKey4LabelList, ConfigLabelDTO.class));
                }
            }*/
        }
        return result;
    }

    private List<DataParamCoreDTO> transformDataParamCoreDTO(Map<Long, String> dataParamMap) {
        List<DataParamCoreDTO> result = new ArrayList<>();
        if (dataParamMap == null) {
            return result;
        }
        for (Long key : dataParamMap.keySet()) {
            String code = dataParamMap.get(key);
            String string = redisValueService.get(code).toString();
            DataParamExtendVO dataParamTemp = JSON.parseObject(string, DataParamExtendVO.class);
            result.add(new DataParamCoreDTO(key, code, dataParamTemp.getReportIdentifier(), dataParamTemp.getPowerCheckDisplay()));
        }
        return result;
    }

    private ConfigDataParamManagementDTO toConfigDataParamManagementDTO(DataParamTempDTO dataParamTempDTO,
                                                                        String equipmentName,
                                                                        Long equipmentId,
                                                                        List<LabelVO> labelList) {
        cleanDataParamTempId(dataParamTempDTO);
        ConfigDataParamManagementDTO configDataParamManagementDTO = BeanUtils.copyToObject(dataParamTempDTO, ConfigDataParamManagementDTO.class);

        CurrentUserDTO currentUser = LocalHolder.getCurrentUser();
        CurrentUserUtils.setCreateDefaultField(configDataParamManagementDTO, currentUser);
        // 设置code
//        String code = setCode(configDataParamManagementDTO);
//        redisValueService.set(code, JSON.toJSONString(new DataParamExtendVO(dataParamTempDTO)), 1L, TimeUnit.HOURS);
        // 重命名
        configDataParamManagementDTO.setName(equipmentName + StrUtil.DASHED + configDataParamManagementDTO.getUnifiedIdentifierName());

        Integer source = dataParamTempDTO.getSource();
        if (DataParamSourceEnum.SYSTEM_CALCULATE.getCode().equals(source)) {
            AlgorithmTempDTO algorithm = dataParamTempDTO.getAlgorithm();
            if (ObjectUtil.isNotEmpty(algorithm)) {
                configDataParamManagementDTO.setAlgorithmId(algorithm.getAlgorithmId());
                configDataParamManagementDTO.setAlgorithmName(algorithm.getAlgorithmName());
                configDataParamManagementDTO.setConfigAlgorithDTO(transformConfigAlgorithm(algorithm));
            }
            configDataParamManagementDTO.setConfigParamDTOList(BeanUtils.copyToList(dataParamTempDTO.getAlgorithm().getParamTempList(), ConfigParamDTO.class));
        }
        configDataParamManagementDTO.setConfigAlarmDTOList(BeanUtils.copyToList(dataParamTempDTO.getAlarmList(), ConfigAlarmDTO.class));
        // 添加设备的标签
//        List<LabelTempDTO> labelTempList = equipmentInfoClient.listEquipmentLabelByEquipmentId(equipmentId);
        List<ConfigLabelDTO> labelDTOList = new ArrayList<>();
        List<LabelTempDTO> labelTempList = dataParamTempDTO.getLabelList();
        labelDTOList.addAll(BeanUtils.copyToList(labelTempList, ConfigLabelDTO.class));
        labelDTOList.addAll(BeanUtils.copyToList(labelList, ConfigLabelDTO.class));
        //configDataParamManagementDTO.setConfigLabelDTOList(labelDTOList);
        return configDataParamManagementDTO;
    }

    private ConfigAlgorithDTO transformConfigAlgorithm(AlgorithmTempDTO algorithm) {
        ConfigAlgorithDTO res = new ConfigAlgorithDTO();

        if (ObjectUtil.isEmpty(algorithm)) {
            return res;
        }
        res.setAlgorithId(algorithm.getAlgorithmId());
        res.setAlgorithName(algorithm.getAlgorithmName());
        res.setRequestType(algorithm.getRequestType());
        res.setAlgorithFormula(algorithm.getAlgorithmFormula());
        res.setScriptPath(algorithm.getScriptPath());
        return res;
    }


    private void cleanDataParamIdAndSetCode(ConfigDataParamManagementDTO configDataParamManagementDTO) {

    }

    private void cleanDataParamTempId(DataParamTempDTO dataParamTempDTO) {
        dataParamTempDTO.setId(null);

        Optional.ofNullable(dataParamTempDTO.getAlarmList())
                .ifPresent(configAlarmDTOList -> configAlarmDTOList
                        .forEach(configAlarmDTO -> configAlarmDTO.setId(null)));
        Optional.ofNullable(dataParamTempDTO.getLabelList())
                .ifPresent(configLabelDTOList -> configLabelDTOList
                        .forEach(configLabelDTO -> configLabelDTO.setId(null)));

        if (DataParamSourceEnum.SYSTEM_CALCULATE.getCode().equals(dataParamTempDTO.getSource())) {
            Optional.ofNullable(dataParamTempDTO.getAlgorithm()).ifPresent(configAlgorithDTO -> configAlgorithDTO.setId(null));
            if (ObjectUtil.isNotEmpty(dataParamTempDTO.getAlgorithm())) {
                Optional.ofNullable(dataParamTempDTO.getAlgorithm().getParamTempList())
                        .ifPresent(configParamDTOList -> configParamDTOList
                                .forEach(configParamDTO -> configParamDTO.setId(null)));
            }
        }
    }



    private DataParam4EquipmentDTO toBuildDataParamEquipment(DataParamInfoVO dataParamTemp) {
        DataParam4EquipmentDTO result = new DataParam4EquipmentDTO();
        ConfigDataParamManagementDTO configDataParamManagement = toBuildConfigDataParamManagementDTO(dataParamTemp);
        result.setConfigDataParamManagement(configDataParamManagement);
        DataParam4EquipmentExtendDTO extend = new DataParam4EquipmentExtendDTO();
        extend.setEquipmentId(dataParamTemp.getEquipmentId());
        extend.setEquipmentCode(dataParamTemp.getEquipmentCode());
        extend.setEquipmentName(dataParamTemp.getEquipmentName());
        extend.setPowerCheckDisplay(dataParamTemp.getPowerCheckDisplay());
        extend.setReportIdentifier(dataParamTemp.getReportIdentifier());
        result.setDataParam4EquipmentExtend(extend);
        return result;
    }

    /**
     * 构建配置数据参数管理 DTO
     *
     * @param dataParamTempVO {@link DataParamInfoVO} 数据参数模板
     * @return {@link ConfigDataParamManagementDTO} 配置数据参数管理 DTO
     */
    private ConfigDataParamManagementDTO toBuildConfigDataParamManagementDTO(DataParamInfoVO dataParamTempVO) {
        ConfigDataParamManagementDTO configDataParamManagementDTO = dataParamTempVO.buildDataParamDTO();
        // 同步设备的状态
        if (ObjectUtil.isNotEmpty(dataParamTempVO.getEquipmentId())) {
            EquipmentInfoDTO equipmentInfoDTO = getById2(dataParamTempVO.getEquipmentId());
            configDataParamManagementDTO.setStatus(equipmentInfoDTO.getStatus());
        }

        if (DataParamSourceEnum.SYSTEM_CALCULATE.getCode().equals(dataParamTempVO.getSource())) {
            ConfigAlgorithDTO configAlgorithDTO = dataParamTempVO.getAlgorithm().buildDTO();
            configDataParamManagementDTO.setConfigAlgorithDTO(configAlgorithDTO);
            // 算法参数
            List<ConfigParamDTO> configParamDTOList = dataParamTempVO.getAlgorithm().getConfigParamList()
                    .stream()
                    .map(ParamTempVO::buildDTO)
                    .collect(Collectors.toList());
            configDataParamManagementDTO.setConfigParamDTOList(configParamDTOList);

            FrequencyVO frequency = dataParamTempVO.getFrequency();
            configDataParamManagementDTO.setFrequency(frequency.getFrequency());
            configDataParamManagementDTO.setFrequencyUnit(frequency.getFrequencyUnit());

            // 添加算法名称
            configDataParamManagementDTO.setAlgorithmName(dataParamTempVO.getAlgorithm().getAlgorithmName());
            configDataParamManagementDTO.setAlgorithmId(dataParamTempVO.getAlgorithm().getAlgorithmId());
        } else if (DataParamSourceEnum.SYSTEM_AUTO_COLLECT.getCode().equals(dataParamTempVO.getSource())) {
            FrequencyVO frequency = dataParamTempVO.getFrequency();
            configDataParamManagementDTO.setFrequency(frequency.getFrequency());
            configDataParamManagementDTO.setFrequencyUnit(frequency.getFrequencyUnit());
        }

        List<ConfigAlarmDTO> configAlarmDTOList = dataParamTempVO.getAlarmList()
                .stream()
                .map(AlarmVO::buildDTO)
                .collect(Collectors.toList());
        configDataParamManagementDTO.setConfigAlarmDTOList(configAlarmDTOList);

        /*List<ConfigLabelDTO> configLabelDTOList = dataParamTempVO.getLabelList()
                .stream()
                .map(LabelVO::buildDTO)
                .collect(Collectors.toList());*/
        //configDataParamManagementDTO.setConfigLabelDTOList(configLabelDTOList);

        return configDataParamManagementDTO;
    }
    public EquipmentInfoDTO getById2(Long id) throws ServiceException {
        EquipmentInfoDO equipmentInfoDO = equipmentInfoDAO.selectById(id);
        Assert.notNull(equipmentInfoDO, EquipmentModelErrorCodeEnum.OBJECT_NOT_FIND);
        EquipmentInfoDTO equipmentInfoDTO = BeanUtils.copyToObject(equipmentInfoDO, EquipmentInfoDTO.class);
        String dockIdentifier = equipmentInfoDTO.getDockIdentifier();
        if (StringUtils.isNotBlank(dockIdentifier)) {
            EquipmentGatewayRelationDO equipmentGatewayRelationDO = equipmentGatewayRelationDAO.selectOne(Wrappers.<EquipmentGatewayRelationDO>lambdaQuery()
                    .eq(EquipmentGatewayRelationDO::getMcbId, dockIdentifier)
                    .last("limit 1"));
            if (equipmentGatewayRelationDO != null) {
                equipmentInfoDTO.setGatewayIdentifier(equipmentGatewayRelationDO.getGwId());
                equipmentInfoDTO.setGatewayName(equipmentGatewayRelationDO.getModel());
            }
        }
        return equipmentInfoDTO;
    }
}
